<?php

namespace app\api\services;

use app\common\libs\Singleton;
use app\common\models\Order\OrderError;
use Exception;
use think\facade\App;
use Yansongda\Pay\Exception\ContainerDependencyException;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Pay;

class AlipayService
{
    use Singleton;

    /**
     * 支付参数配置
     * @var array
     */
    protected $config = [
        'alipay' => [
            'default' => [
                // 必填-支付宝分配的 app_id
                'app_id' => '2021004138684404',
                // 必填-应用私钥 字符串或路径
                //'app_secret_cert' => 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCQcpouAhoalxHhNbFPBpifpEWMX9ROelu6Gj6v6Gu1Y2LHAtSMYBLvWjgMpAjbZZenYaC5KeBJD3/rPlpVJ2w9lhXO+4YbsIhlsAsuP1IPTTH4FqN/4w0HYUYsqggMzKvJQ5aS11dfCjM8FkbjOENY+yOkXckyVFdrKpEWihpkS64NpdbHSPgoLWN5FCnl5OUdJV66c9UqqSROLqUCoN7S8kCn8+PgAD3MrEuHKK81s/ZwsXSx7vdW58NiXEaI3QNA8bN7S83G3BgTrXZ3+J6H0GzLe7DNqHpauuSNZczUIs1qBRo8cxnJpK088ioqkQWOR/fQIRmr2a5SsICVFiivAgMBAAECggEAX4WZ1fEH6Cuc5EyIe5UGGxQb9e9tS5R40kIG0HcnuyUFLkv92PKzstr7k8hqHwQ43LSf/7LkogwA8MUkIYnXd4an11/X2LnOCUj4q9Wt43aOI9x8tNamSAoYyPKMLkKvG4J5sZN8MNpi9UpaCGqthstVT53Brmm+AZ19ouUi/M1azNppPlVz/QCzH1aRIJZIQXWQhTuSm7IxyjVEUxRu5aOm3wDhRw16M+IdKe/YrfcfK6MftqpblueY5uhpl80hkwugaodgkKXfORDmrOr6bpbMKYzWv1O+zfQwTwJfZE4sda2k2Baw5Nsm57rJnJCv5kJlNLaWsbk7zuZnUl9JOQKBgQDa5qVGKB70BbCpxcYU+OnzvNKzPhMcSpv2hRZHQhIbxnvhhaG8H7GvLtEhiKR+zMTMnNNDKQBdaIlckzBhT5U1tIb2bafbVPCotSfvilAyOvgXDgLxz6FZ+uA8JrzOK6NsipDjkmlFnHuL/6p0ArI9ZUAr614CxsZAq2cCDnyTNQKBgQCo7a+lPQdCB9fKqLEt7EHWsjw5Q9MNMeSc+Bcd4OxQ2w29RM6WuxYrCqLV2xGh76SI2QXfxcXcGVEeOltInkRNxl5ZVO0lIdM9tcopPWE2izoH65lKm3ZJuwWF1SIbnaYtK6QLcF8zngASfxRBHSvJoyd/A6+eKVStzseNcSwE0wKBgQDLrT3s6Fncrgqx/P6Q9wYgLvpRoxl/AoDZwP14siZNR8JulbtmYoseuE4IiK6d+QPIasc7v0PCpgjhZWbntHfeL6pAUsmTkBYYs+6DuMtj4XCDaxscShgUtBS+g0C8COiXjtq/lLR0++QM4IeGSBf2fmZWNzsTFEbVV2aSCE6rXQKBgCl/Mc2Sf0zuJklHRTb1uXqnD/o1OgwcvH7+xpb1YLfAB9D9rQ4D6T8rfrKv/NXdy3o+bZ35tFAL/AxD45akIj1ExHqHTTX46C5ZkM6uoEnIy7mUW3SjWdxkz8d/gsBr6p1gAg05Tnmcj4H7q5sPMml25cXivupIVt/XUtfg/CI3AoGBAM8RbHHW3JmCqkgU9XghOjX2UKvujCDTWfcOmN7eSydS9n2LFrWlzXbJkaivzc1wL/gPnPS8bftPJe/BlTXykaRsHYNA7vc8lhJ8Y1RgxdiHBhJLTSa2BDPy1B+kCkVb9wMIQVAtNUXnXJRU8UR6cxt3Jo1pX95KVPJsPlUWxfEW',
                'app_secret_cert' => 'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCN/Wy+pcYhanCCZQ6g1F2/ndjyU9Pbn1GFAzTy0LXfiyUnBjPPmNYlWK4Qb+JV66sA5bzdG7OZ7Snng8swPNuj1hFihJQYivLIJ1TKTZELi+ypL/9RO17HPKjecHQ7fCp+K5z2oBxyotYmpeBCQaCFe6z0uPGBp9bvTTTvPCZWvdmybFg6DGHvASXqb3u2GPi5JFq7iUTUuierVvHvrxk8bxNMUoC3VwQHIdjpGoH6AOqgaOukXczuLG4gxA8pTEfNZTwjIHzG2YMO95IPUOo+1XzpYc980WoeSwPuRxXhzsEnrnEhhnHMG0jGF3ex3iQJLfwoafDTVD0XLxhmakXPAgMBAAECggEAEC8oq/pdQQXO2S4HotFR9jtZtRVU+p2IPy8EZADiGh7UF0SftzPmhM881+bI155LGYkWI+W6bPsZYagmCtOE/YGy7ZXLA5ki3ymMgpqgw74pNYehBHNN9Eu3u9L5jKY0ebki5QGO/IoO+szBaQvt7gkQx7wk2vB0kUYtmG80t4I0nKMA3ogRO9RVS3MP7KE+fUH725nr8YNtuRfl7xHH7BudESImjVfBAhm5LRerDo0WYLaLZ8TfnMrwUs8pPY7EYTzsbuIMMH5sz+ryx3pnHLH9JXGXRX18XQvRz7p9sODTVbWRN3TNuwNT+aB+Jps+gEMbaMYefcYagf8tmTU9QQKBgQDRZpNpOEV6pAP6pdcQU2AfUxZNTK2Nol76MCDNS2gaIPbIK63tSMrBepRK3vuSXo8tlewT6OeA9Sn3XgHRj8KK/Dg8Bfn9/yjGISoE7NNQ0YoyMjBQomoC9P0MSCiXBHmrmebAT+T9ROhkCM+12jBJtovRjwnEZsMOBB9+uY4XnwKBgQCtloBlUwjHfldC/ZMpzXf4otWa6mBbk7SmTQcoT0vlwEIJk65jVWIG2t67YrcXbAJT5/rinpjLQ7NC0MI9KfQL6by96PltWiQdsmLgvWvCK8zFWsZpBSW+8aSkYyT1UyLnroL7Jo1VAXB6VM7b2bACF+hLgLeWmPYQ+0m8ninj0QKBgQChohbpIhlnWBEGOVqvbFwG8eCGHEjeydWcMugu7yTU/lrfGfAv938iJ1cuD76KNdk467+FgsKnpRYWrgajVt9o3tUdZ9OW/ozfmpvPn2phuMx+gIUQyL0huS9WeqByKW8tSSd3jHQKF1V2WeLS0S9yxqhYQpvccSHgwMf6zoniqwKBgGc5pEicxA+9ta6ElEq7gKg+TL++uGY8w6RREfyKixuo5JxFUeKIF67z4JeV8ELhW9EBllPE9B+LtsH42kj89b9P04krTYgVnnx6ZAo5GidxXGfPv0UcZoHRuJJ40rWAJrWXNRScrFbscDKO1CQwo1XbWavscz/+3fTjOcoMU+TBAoGBAMQ1yUmgGiwVJ0ShOpcn+/wyMYOAe4NVsiUMmWZV2oFumIFeer/6g/f/z8zrtHLyTpvGyGFzg5UO6AHt29lj5qDtMvbHuCYVskUKDYpyoAKO7XdZkiEA2YV2x6flWAaSTgQI6p60DsnWumVV3nfygq4+sqpuztRfUan1QVujk27A',
                // 必填-应用公钥证书 路径
                'app_public_cert_path' => 'cert/appCertPublicKey_2021004138684404.crt',
                // 必填-支付宝公钥证书 路径
                'alipay_public_cert_path' => 'cert/alipayCertPublicKey_RSA2.crt',
                // 必填-支付宝根证书 路径
                'alipay_root_cert_path' => 'cert/alipayRootCert.crt',
                'return_url' => '',
                'notify_url' => '/api/callback/alipayCallback',
                // 选填-第三方应用授权token
                'app_auth_token' => '',
                // 选填-服务商模式下的服务商 id，当 mode 为 Pay::MODE_SERVICE 时使用该参数
                'service_provider_id' => '',
                // 选填-默认为正常模式。可选为： MODE_NORMAL, MODE_SANDBOX, MODE_SERVICE
                'mode' => Pay::MODE_NORMAL,
            ],
        ],
        'logger' => [ // optional
            'enable' => false,
            'file' => './logs/alipay.log',
            'level' => 'info', // 建议生产环境等级调整为 info，开发环境为 debug
            'type' => 'single', // optional, 可选 daily.
            'max_file' => 30, // optional, 当 type 为 daily 时有效，默认 30 天
        ],
        'http' => [ // optional
            'timeout' => 5.0,
            'connect_timeout' => 5.0,
            // 更多配置项请参考 [Guzzle](https://guzzle-cn.readthedocs.io/zh_CN/latest/request-options.html)
        ],
    ];

    public function __construct()
    {
        $this->extracted();
    }

    public function appPay($payInfo, $paySubType): string
    {
        $this->config['alipay']['default']['notify_url'] = 'https://' . $_SERVER['HTTP_HOST'] . $this->config['alipay']['default']['notify_url'];
        //$totalAmount = env('test.is_test') == 1 ? rand(1, 10) : $payInfo['pay_price'];
        $totalAmount = $payInfo['pay_price'];
        $data = [
            'out_trade_no' => $payInfo['pay_no'],
            'total_amount' => $totalAmount,
            'subject' => '支付订单',
        ];
        if ($paySubType == 'app') {
            $ret = Pay::alipay($this->config)->app($data)->getBody()->getContents();
        } else {
            $ret = Pay::alipay($this->config)->wap($data)->getBody()->getContents();
        }
        return $ret;
    }


    /**
     * 退款
     * @throws InvalidParamsException
     * @throws ContainerDependencyException
     * @throws ServiceNotFoundException
     * @throws ContainerException
     */
    public function refund($orderNo, $refundAmount)
    {
        $order = [
            'out_trade_no' => $orderNo,
            'refund_amount' => $refundAmount,
        ];
        return Pay::alipay($this->config)->refund($order);
    }

    /**
     * 查询订单
     * @throws InvalidParamsException
     * @throws ContainerDependencyException
     * @throws ServiceNotFoundException
     * @throws ContainerException
     */
    public function find($out_trade_no)
    {
        $order = [
            'out_trade_no' => $out_trade_no,
            'bill_type' => 'trade'
        ];
        $alipay = Pay::alipay($this->config);
        return $alipay->find($order);
    }

    public function transfer($txOrderNo, $price, $aliName, $aliAccount): array
    {
        $result = Pay::alipay($this->config)->transfer([
            'out_biz_no' => $txOrderNo,
            'trans_amount' => (string)$price,
            'product_code' => 'TRANS_ACCOUNT_NO_PWD',
            'biz_scene' => 'DIRECT_TRANSFER',
            'payee_info' => [
                'identity' => $aliAccount,
                'identity_type' => 'ALIPAY_LOGON_ID',
                'name' => $aliName,
            ],
        ]);

        if ($result['code'] == 10000 && $result['status'] == 'SUCCESS') {
            return ['code' => 1, 'data' => $result];
        } else {
            return ['code' => 0, 'data' => $result['sub_msg']];
        }
    }

    public function aliCallback(): bool
    {
        $alipay = Pay::alipay($this->config);

        try {
            $data = $alipay->callback(); // 是的，验签就这么简单！
            OrderError::getInstance()->insert(['text' => json_encode($data)]);
            // 请自行对 trade_status 进行判断及其它逻辑进行判断，在支付宝的业务通知中，只有交易通知状态为 TRADE_SUCCESS 或 TRADE_FINISHED 时，支付宝才会认定为买家付款成功。
            // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号；
            // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额）；
            // 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）；
            // 4、验证app_id是否为该商户本身。
            // 5、其它业务逻辑情况
            if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                // @todo 更新订单状态，支付完成
                $info = [
                    'pay_status' => 2,
                    'pay_no' => $data['out_trade_no'],
                    'money' => $data['total_amount'],
                    'trade_no' => $data['trade_no'],
                    'receipt_data' => '',
                ];
                OrderError::getInstance()->insert(['text' => "进来支付宝回调了：" . json_encode($info)]);
                $event["exchange"] = config('rabbitmq.order_callback_queue');
                RabbitMqService::send($event, $info);
            }
        } catch (\Exception $e) {
            OrderError::getInstance()->insert(['text' => $e->getMessage()]);
            return false;
        }
        return true;
    }

    /**
     * @return void
     */
    public function extracted(): void
    {
        $this->config['alipay']['default']['app_public_cert_path'] = App::getRootPath() . $this->config['alipay']['default']['app_public_cert_path'];
        $this->config['alipay']['default']['alipay_public_cert_path'] = App::getRootPath() . $this->config['alipay']['default']['alipay_public_cert_path'];
        $this->config['alipay']['default']['alipay_root_cert_path'] = App::getRootPath() . $this->config['alipay']['default']['alipay_root_cert_path'];
    }


}